package cn.flying.cloud.auth.web;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.flying.cloud.auth.security.details.CustomUserDetailService;
import cn.flying.cloud.auth.security.details.UserDetail;
import cn.flying.cloud.auth.security.exception.TokenIllegalException;
import cn.flying.cloud.auth.security.vo.LoginResult;
import cn.flying.cloud.base.common.constants.Constants;
import cn.flying.cloud.base.common.enums.RtCodeEnum;
import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.base.common.utils.lang.CaptchaUtil;
import cn.flying.cloud.base.common.vo.Rt;
import cn.flying.cloud.base.redis.service.RedisService;

/**
 * 认证服务请求处理器
 *
 * @author: admin
 * @date: 2022年05月22日 17:58
 * @version: 1.0
 */
@RestController
@RequestMapping("/auth/")
public class AuthController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private CustomUserDetailService customUserDetailService;
    @Resource
    private RedisService redisService;

    @RequestMapping("/user/captcha")
    public void captcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String uid = request.getParameter("uid");
        /*
             1.生成验证码
             2.把验证码上的文本存在缓存中
             3.把验证码图片发送给客户端
             */
        CaptchaUtil captchaUtil = new CaptchaUtil(120, 38);
        BufferedImage image = captchaUtil.getImage();
        logger.info("生成的验证码：{}, uid：{}", captchaUtil.getText(), uid);
        //验证码放入缓存
        redisService.set(Constants.AUTH_CODE + ":captcha:" + uid, captchaUtil.getText(), 3 * 60 * 1000L);
        captchaUtil.output(image, response.getOutputStream());
    }

    /**
     * 刷新Token
     *
     * @param refreshToken
     * @return
     */
    @PostMapping("/user/refresh")
    public Rt<?> refresh(String refreshToken) {
        try {
            boolean validated = Ft.Jwt.validateToken(refreshToken);
            if (!validated) {
                logger.warn("refresh_token失效了");
                return Rt.error("refresh_token失效了");
            }

            //如果token有效，则从token中解析出用户名
            Map<String, Object> map = Ft.Jwt.parseToken(refreshToken);
            if (map == null) {
                throw new TokenIllegalException(RtCodeEnum.R10005.getDesc());
            }
            String username = (String) map.get("sub");
            UserDetail userDetail = customUserDetailService.findUserByUsername(username);

            // 重新生成Token
            String jwtId = UUID.randomUUID().toString();
            long expire = 60 * 60 * 1000L;
            String accessToken;
            try {
                refreshToken = Ft.Jwt.createToken(userDetail.getUsername(), userDetail.getUsername(), jwtId, expire * 10);
                accessToken = Ft.Jwt.createToken(userDetail.getUsername(), userDetail.getUsername(), jwtId, expire);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            LoginResult result = new LoginResult();
            result.setTokenType("bearer");
            result.setAccessToken(accessToken);
            result.setExpiresIn(Objects.requireNonNull(Ft.Jwt.getExpiredDate(accessToken)).getTime());
            result.setJti(jwtId);
            result.setRefreshToken(refreshToken);
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("userName", userDetail.getUsername());
            userInfo.put("avatar", userDetail.getAvatar());
            userInfo.put("tenantId", userDetail.getTenantId());
            userInfo.put("userId", userDetail.getUserId());
            result.setUserInfo(userInfo);

            //将token放入缓存
            String tokenKey = Constants.ACCESS_TOKEN + ":" + jwtId;
//            redisService.set(tokenKey, JSON.toJSONString(userDetail), expire);
            redisService.set(tokenKey, accessToken, expire);

            return Rt.success(result);
        } catch (Exception e) {
            logger.error("refresh_token校验失败", e);
            return Rt.error("refresh_token校验失败");
        }
    }
}
